package com.hlkj.util.dom4j;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import net.sf.json.xml.XMLSerializer;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * dom4j解析XML
 * 
 * @author zhukui
 */
public class Dom4jPraseXML {
	/**
	 * 迭代XML
	 */
	@SuppressWarnings("unchecked")
	public static List iteratorNode(String xml) throws DocumentException {
		ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
		Document document = DocumentHelper.parseText(xml);
		Element root = document.getRootElement();
		iteratorNode(root, list);
		System.out.println("iteratorList=" + list);
		return list;
	}

	/**
	 * 迭代XML
	 */
	@SuppressWarnings("unchecked")
	public static List iteratorNodeMap(String xml) throws DocumentException {
		Map<String, String> map = new HashMap<String, String>();
		Document document = DocumentHelper.parseText(xml);
		Element root = document.getRootElement();
		iteratorNode(root, map);
		System.out.println("iteratorMap=" + list);
		return list;
	}

	static int i = 0;

	/**
	 * 递归遍历节点获得对应的子节点 employee->sex->name->age
	 */
	@SuppressWarnings("unchecked")
	public static void iteratorNode(Element root, List<Map<String, String>> list) {
		HashMap<String, String> map = null;
		// 对root下的所有employee迭代
		// Iterator iter = root.elementIterator("employee"); iter.hasNext();

		// 对root节点下的所有子节点进行遍历
		for (Iterator iter = root.elementIterator(); iter.hasNext();) {
			map = new HashMap<String, String>();
			Element element = (Element) iter.next();
			if (element == null)
				continue;
			// 获取属性名和它的值
			for (Iterator attrs = element.attributeIterator(); attrs.hasNext();) {
				Attribute attr = (Attribute) attrs.next();
				if (attr == null)
					continue;
				String attrName = attr.getName();
				String attrValue = attr.getValue();
				map.put(attrName, attrValue);
			}
			// true if this element is empty or only contains text content.
			if (element.isTextOnly()) {
				String innerName = element.getName();
				String innerValue = element.getText();
				map.put(innerName, innerValue);
				list.add(map);
			} else {
				// list.add(map);
				// 递归调用
				iteratorNode(element, list);// 测试xml只调用了2次
			}
		}

	}

	HashMap<String, String> map = null;
	static ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();

	/**
	 * 递归遍历节点获得对应的子节点 employee->sex->name->age
	 */
	@SuppressWarnings("unchecked")
	public static void iteratorNode(Element root, Map<String, String> map) {
		// 对root节点下的所有子节点进行遍历
		for (Iterator iter = root.elementIterator(); iter.hasNext();) {

			Element element = (Element) iter.next();
			if (element == null)
				continue;
			// 获取属性名和它的值
			for (Iterator attrs = element.attributeIterator(); attrs.hasNext();) {
				Attribute attr = (Attribute) attrs.next();
				if (attr == null)
					continue;
				String attrName = attr.getName();
				String attrValue = attr.getValue();
				map.put(attrName, attrValue);
			}
			// true if this element is empty or only contains text content.
			if (element.isTextOnly()) {
				String innerName = element.getName();
				String innerValue = element.getText();
				map.put(innerName, innerValue);
				// list.add(map);
			} else {
				if (map.size() > 0)
					list.add(map);
				// 递归调用
				// map = new HashMap<String, String>();
				iteratorNode(element, new HashMap<String, String>());// 测试xml只调用了2次
				System.out.println(i);
				i++;
			}
		}
	}

	/**
	 * 创建标准xml
	 * 
	 * @param fileName
	 */
	public static void createXml(String fileName) {
		Document document = DocumentHelper.createDocument();
		Element employees = document.addElement("employees");
		employees.addAttribute("element_name", "employee");
		Element employee = employees.addElement("employee");
		Element name = employee.addElement("name");
		name.setText("Json");
		Element sex = employee.addElement("sex");
		sex.setText("man");
		Element age = employee.addElement("age");
		age.setText("29");
		try {
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding("UTF-8"); // 指定XML编码
			XMLWriter xmlWriter = new XMLWriter(new FileWriter(fileName),
					format);
			xmlWriter.write(document);
			xmlWriter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 将XML格式的document转化成List对象
	 * 
	 * @param xml
	 * @return List<Map<String, String>>
	 * @category XML格式:<?xml version="1.0" encoding="UTF-8"?> <employees
	 *           element_name="employee"> <employee>
	 *           <name>Json</name><sex>man</sex><age>29</age> </employee>
	 *           <employee> <name>Jax</name><sex>man</sex><age>26</age>
	 *           </employee> </employees>
	 */
	@SuppressWarnings("unchecked")
	public static List<Map<String, String>> getListFromXML(String xml) {
		try {
			ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
			Document document = DocumentHelper.parseText(xml);
			Element root = document.getRootElement();
			// 根节点的组子节点
			String element_name = root.attributeValue("element_name");
			// 取XML根节点下名为elementName的子节点,并暂时存放为list
			List<Element> elements = root.elements(element_name);
			// 遍历XML中取得的elements
			Map<String, String> map = null;
			for (Element item : elements) {
				List<Element> element_son = item.elements();
				map = new HashMap<String, String>();
				for (Element item_son : element_son) {

					// 获取属性名和它的值
					for (Iterator attrs = item_son.attributeIterator(); attrs
							.hasNext();) {
						Attribute attr = (Attribute) attrs.next();
						if (attr == null)
							continue;
						String attrName = attr.getName();
						String attrValue = attr.getValue();
						map.put(attrName, attrValue);
					}

					// 取得对应字段的值
					String text = item_son.getText();
					// 若值不为空，将对应字段的值转化为对应类型后存入Object对应的字段fields
					if ((text != null) && (!text.trim().equals(""))) {
						map.put(item_son.getName(), text);
					}
				}
				list.add(map);
			}
			System.out.println("list=" + list);
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将XML格式内容的File文件转化成List对象
	 * 
	 * @param xml
	 * @return List<Map<String, String>>
	 * @category XML格式:<?xml version="1.0" encoding="UTF-8"?> <employees
	 *           element_name="employee"> <employee>
	 *           <name>Json</name><sex>man</sex><age>29</age> </employee>
	 *           <employee> <name>Jax</name><sex>man</sex><age>26</age>
	 *           </employee> </employees>
	 */
	@SuppressWarnings("unchecked")
	public static List<Map<String, String>> getListFromXMLFile(String filename) {
		try {
			SAXReader reader = new SAXReader();
			Document document = reader.read(new File(filename));
			Element root = document.getRootElement();

			ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
			// 根节点的组子节点
			String element_name = root.attributeValue("element_name");
			// 取XML根节点下名为elementName的子节点,并暂时存放为list
			List<Element> elements = root.elements(element_name);
			// 遍历XML中取得的elements
			Map<String, String> map = null;
			for (Element item : elements) {
				List<Element> element_son = item.elements();
				map = new HashMap<String, String>();
				for (Element item_son : element_son) {

					// 获取属性名和它的值
					for (Iterator attrs = item_son.attributeIterator(); attrs
							.hasNext();) {
						Attribute attr = (Attribute) attrs.next();
						if (attr == null)
							continue;
						String attrName = attr.getName();
						String attrValue = attr.getValue();
						map.put(attrName, attrValue);
					}

					// 取得对应字段的值
					String text = item_son.getText();
					// 若值不为空，将对应字段的值转化为对应类型后存入Object对应的字段fields
					if ((text != null) && (!text.trim().equals(""))) {
						map.put(item_son.getName(), text);
					}
				}
				list.add(map);
			}
			System.out.println("getXmlFileList=" + list);
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * xml转json
	 * 
	 * @param xml
	 * @return JSON
	 */
	public static JSON XML2Json(String xml) {
		XMLSerializer xmlSerializer = new XMLSerializer();
		JSON json = xmlSerializer.read(xml);
		System.out.println("xml2json=" + json);
		return json;
	}

	/**
	 * json转xml {"node":{"key":{"@label":"key1","#text":"value1"}}} conver
	 * <o><node class="object"><key class="object"
	 * label="key1">value1</key></node></o>
	 * 
	 * @param json
	 * @return xml
	 */
	public static String Json2XML(String json) {
		try {
			XMLSerializer serializer = new XMLSerializer();
			JSON jsonObject = JSONSerializer.toJSON(json);
			return serializer.write(jsonObject);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	public static List<HashMap<String, Object>> Dom2List(String xml)
			throws DocumentException {
		Document document = DocumentHelper.parseText(xml);
		HashMap<String, Object> map = new HashMap<String, Object>();
		List<HashMap<String, Object>> arrayList = new ArrayList<HashMap<String, Object>>();
		if (document == null)
			return arrayList;
		Element root = document.getRootElement();
		for (Iterator iterator = root.elementIterator(); iterator.hasNext();) {
			Element e = (Element) iterator.next();
			List list = e.elements();
			map = new HashMap<String, Object>();

			if (list.size() > 0) {// 元素下面有元素
				map.put(e.getName(), Dom2Map(e));
			} else {
				// {@name=测试, test=test, @id=0002}
				if (e.attributeCount() > 0) {
					 HashMap hashMap = new HashMap();
					for (Iterator attrs = e.attributeIterator(); attrs
							.hasNext();) {
						Attribute attr = (Attribute) attrs.next();
						if (attr == null)
							continue;

						String attrName = attr.getName();
						String attrValue = attr.getValue();
						 hashMap.put("@" + attrName, attrValue);
					}
					 hashMap.put(e.getName(), e.getText());
					 map.put(e.getName(), hashMap);
				} else {
					 map.put(e.getName(), e.getText());
				}
			}
			arrayList.add(map);
		}
		System.out.println("Dom2List=" + arrayList);
		return arrayList;
	}

	@SuppressWarnings("unchecked")
	public static Map Dom2Map(Element e) {
		Map map = new HashMap();
		List list = e.elements();
		if (list.size() > 0) {
			for (int i = 0; i < list.size(); i++) {
				Element iter = (Element) list.get(i);
				List mapList = new ArrayList();

				if (iter.elements().size() > 0) {
					Map m = Dom2Map(iter);
					if (map.get(iter.getName()) != null) {
						Object obj = map.get(iter.getName());
						if (!obj.getClass().getName().equals(
								"java.util.ArrayList")) {
							mapList = new ArrayList();
							mapList.add(obj);
							mapList.add(m);
						}
						if (obj.getClass().getName().equals(
								"java.util.ArrayList")) {
							mapList = (List) obj;
							mapList.add(m);
						}
						map.put(iter.getName(), mapList);
					} else
						map.put(iter.getName(), m);
				} else {
					if (map.get(iter.getName()) != null) {
						Object obj = map.get(iter.getName());
						if (!obj.getClass().getName().equals(
								"java.util.ArrayList")) {
							mapList = new ArrayList();
							mapList.add(obj);
							mapList.add(iter.getText());
						}
						if (obj.getClass().getName().equals(
								"java.util.ArrayList")) {
							mapList = (List) obj;
							mapList.add(iter.getText());
						}
						map.put(iter.getName(), mapList);
					} else {

						if (iter.attributeCount() > 0) {
							HashMap hashMap = new HashMap();
							for (Iterator attrs = iter.attributeIterator(); attrs
									.hasNext();) {
								Attribute attr = (Attribute) attrs.next();
								if (attr == null)
									continue;

								String attrName = attr.getName();
								String attrValue = attr.getValue();
								hashMap.put("@" + attrName, attrValue);
							}
							hashMap.put(iter.getName(), iter.getText());
							map.put(iter.getName(), hashMap);
							// map.putAll(hashMap);
						} else {
							map.put(iter.getName(), iter.getText());
						}
					}
				}
			}
		} else {
			for (Iterator attrs = e.attributeIterator(); attrs.hasNext();) {
				Attribute attr = (Attribute) attrs.next();
				if (attr == null)
					continue;

				String attrName = attr.getName();
				String attrValue = attr.getValue();
				map.put("@" + attrName, attrValue);
			}
			map.put(e.getName(), e.getText());
		}
		return map;
	}

	/**
	 * 测试
	 */
	public static void main(String[] args) throws DocumentException {
		String xml = "<?xml version='1.0' encoding='UTF-8'?>"
				+ "<employees element_name='employee' id='001'><test name='测试' id='0002'>test</test><employee><name id='001'>Json</name><sex>man</sex><age>29</age></employee>"
				+ "<employee><name name='green'><name1 name='name1'>Jax1</name1><name2>Jax2</name2></name><sex>man</sex><age>26</age></employee></employees>";

		// String xml = "<?xml version='1.0' encoding='UTF-8'?>"
		// +
		// "<test><people id='0001'><name type='String'><first>jim</first><last type='String'>green</last></name><age type='int'>25</age></people><department type='String'>研发部</department></test>";
		try {
			// createXml("Emp.xml");
			// getListFromXML(xml);
			// XML2Json(xml);
			// iteratorNode(xml);
			// iteratorNodeMap(xml);
			// getListFromXMLFile("Emp.xml");
			Dom2List(xml);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
